/* * Sun Public License Notice * * The contents of this file are subject to the Sun Public License * Version 1.0 (the "License"). You may not use this file except in * compliance with the License. A copy of the License is available at * http://www.sun.com/ * * The Original Code is Forte for Java, Community Edition. The Initial * Developer of the Original Code is Sun Microsystems, Inc. Portions * Copyright 1997-2000 Sun Microsystems, Inc. All Rights Reserved. */ package org.netbeans.modules.vcs; import java.io.*; import java.util.*; import java.beans.*; import java.text.*; import org.netbeans.modules.vcs.util.*; import org.netbeans.modules.vcs.cmdline.exec.*; import org.openide.*; import org.openide.util.*; import org.openide.filesystems.FileObject; import org.openide.filesystems.RepositoryListener; /** This class is used by CommandLineVcsFileSystem to access files and directories *in both VCS and local disk. It holds tree of directories that were loaded from VCS *with list of their files and subdirectories in a memory cache. <br> *Memory cache is also saved to disk cache (in NetBeansHome/system/vcs/cache directory). *This enables fast access to structure of directories after restart of IDE. <br> *VCS directories are first searched for in memory cache than in disk cache. *If they are not found in disk cache they are automatically readed from VCS. *Local directories are not chached and are readed again every time the directory is refreshed. *Local directories can be refreshed automatically by setting refresh time greater than 0. *VCS directories are never refreshed automatically. To refresh VCS directories from VCS user has to *call <B>Version Control|Refresh</B> action on the directory. * @author Michal Fadljevic, Pavel Buzek */ //------------------------------------------- public class VcsCache implements DirReaderListener, RepositoryListener { private Debug E=new Debug("VcsCache", true); // NOI18N private Debug D=E; /** All directories by full path. [key='path/to/some/dir' value=VcsDir] * @associates VcsDir */ private Hashtable dirsByName=new Hashtable(200); private VcsFileSystem fileSystem=null; private String cacheDir=""; // NOI18N public final String localStatusStr = g("CTL_StatusLocal"); // NOI18N private boolean localFilesAdd = true; private volatile int numRefreshThreads = 0; private volatile boolean lastCanceled = false; /** * @associates String */ private volatile Vector pathsQueue = null; //------------------------------------------- public VcsCache(VcsFileSystem fileSystem, String cacheDir){ this.fileSystem=fileSystem; this.cacheDir=cacheDir; WeakListener.Repository wl = new WeakListener.Repository (this); TopManager.getDefault ().getRepository ().addRepositoryListener (wl); numRefreshThreads = 0; lastCanceled = false; pathsQueue = new Vector(); } public void fileSystemAdded(final org.openide.filesystems.RepositoryEvent p1) { } public void fileSystemPoolReordered(final org.openide.filesystems.RepositoryReorderedEvent p1) { } /** Remove cache directory when filesystem is removed. */ public void fileSystemRemoved(final org.openide.filesystems.RepositoryEvent ev) { if(fileSystem.equals (ev.getFileSystem ())) { File dir = new File (cacheDir); if(dir.exists () && dir.isDirectory () && dir.canWrite ()) { if(!deleteDir (dir)) System.out.println("Cannot delete VCS cache directory:"+dir.getPath ()); // NOI18N } fileSystem.setCustomRefreshTime(0); //@Yury Kamen@// } } private boolean deleteDir (File dir) { // System.out.println("removing cache dir:"+dir.getPath ()); // NOI18N return MiscStuff.deleteRecursive(dir); } public void setLocalFilesAdd (boolean localFilesAdd) { this.localFilesAdd = localFilesAdd; } public boolean isLocalFilesAdd () { return localFilesAdd; } //------------------------------------------- private String arrayToLine(String[] sa){ StringBuffer sb=new StringBuffer(100); for(int i=0;i<sa.length;i++){ sb.append(sa[i].trim()+"|"); // NOI18N } return new String(sb); } //------------------------------------------- private void writeDirToDiskCache(String path, Vector rawData){ String dirName=cacheDir+ (path.equals("")?"":(File.separator+path)); // NOI18N //D.deb("writeDirToDiskCache() dirName='"+dirName+"'"); // NOI18N File d=new File(dirName); if( d.isDirectory()==false ){ if( d.mkdirs()==false ){ E.err("Cannot create dir "+dirName); // NOI18N return ; } } BufferedWriter out = null; try{ out = new BufferedWriter( new OutputStreamWriter( new BufferedOutputStream( new FileOutputStream(dirName+File.separator+"list.txt")))); // NOI18N int len=rawData.size(); //D.deb("writeDirToDiskCache("+path+", "+rawData+", len = "+len); for(int i=0;i<len;i++){ String[] elements=(String[])rawData.elementAt(i); out.write( arrayToLine(elements) +"\n"); // NOI18N } } catch (IOException e){ E.err(e,"writeDirToDiskCache() failed for "+dirName); // NOI18N } finally { try { if (out != null) out.close(); } catch (IOException e) { E.err(e,"writeDirToDiskCache() failed for "+dirName); // NOI18N } } } private void writeDirToDiskCacheRecursive(VcsDir dir, VcsDirContainer rawData) { if (dir == null || rawData == null) return; writeDirToDiskCache(dir.getPath(), (Vector) rawData.getElement()); String[] subdirs = dir.getSubdirs(); for(int i = 0; i < subdirs.length; i++) { VcsDir subdir = dir.getDir(subdirs[i]); //D.deb("Putting '"+subdirs[i]+"' under '"+subdir.getPath()+"' to cache."); if (subdir != null) { writeDirToDiskCacheRecursive(subdir, rawData.getDirContainer(subdirs[i])); } } } private void renameDirInDiskCache(String oldName, String newName) { String oldPath = cacheDir + File.separator + oldName; String newPath = cacheDir + File.separator + newName; File oldF = new File(oldPath); File newF = new File(newPath); boolean success = oldF.renameTo(newF); if (!success) { E.err("renameDirInDiskCache failed for "+oldPath+" -> "+newPath); } } //------------------------------------------- /** Add the folder in memory cache and put it in the list of parent`s subdirectories. * @param path path to folder from root of VCS */ public void addFolder(String path) { D.deb("addFolder('"+path+"')"); // NOI18N String dirName=MiscStuff.getDirNamePart(path); String fileName=MiscStuff.getFileNamePart(path); D.deb("dirName="+dirName+", fileName="+fileName); // NOI18N VcsDir parent=getDir(dirName); VcsDir kid=new VcsDir(fileName); kid.setLocal(true); kid.setStatus(localStatusStr); parent.add(kid); registerInMemoryCache(path,kid); heyDoRefreshDir(path); } public void rename(String oldName, String newName) { VcsFile file = getFile(oldName); D.deb("rename ("+oldName+", "+newName+"), file = "+file); if (file != null) { file.setName(MiscStuff.getFileNamePart(newName)); return; } VcsDir dir = getDir(oldName); if (dir != null) { VcsDir newDir = (VcsDir) dir; renameDirInDiskCache(oldName, newName); unregisterFromMemoryCacheRecursive(newDir); newDir.rename(newName); registerInMemoryCacheRecursive(newName, newDir); } } //------------------------------------------- private void registerInMemoryCache(String path, VcsDir dir){ D.deb("registerInMemoryCache('"+path+"',"+dir+")"); // NOI18N String[] subdirs = dir.getSubdirs(); for(int i = 0; i < subdirs.length; i++) { VcsDir subdir = dir.getDir(subdirs[i]); D.deb("Putting '"+subdirs[i]+"' under '"+subdir.getPath()+"' to cache."); if (subdir != null) { VcsDir lastDir = (VcsDir) dirsByName.get(subdir.getPath()); if (lastDir == null) dirsByName.put(subdir.getPath(), subdir); else { lastDir.setStatus(subdir.getStatus()); lastDir.setLocker(subdir.getLocker()); lastDir.setLocal(subdir.isLocal()); lastDir.setLoaded(subdir.isLoaded()); D.deb("Dir "+subdir.getPath()+" already exists in the cache, status ["+subdir.getStatus()+"] updated"); D.deb("lastDir = "+lastDir); dir.remove(subdir); dir.add(lastDir); } } /* dirsByName.put(/*((path.length() > 0) ? path+"/" : "")+*//*subdirs[i], dir.getDir(subdirs[i])); */ } dirsByName.put(path,dir); } private void registerInMemoryCacheRecursive(String path, VcsDir dir){ D.deb("registerInMemoryCacheRecursive('"+path+"',"+dir+")"); // NOI18N String[] subdirs = dir.getSubdirs(); for(int i = 0; i < subdirs.length; i++) { VcsDir subdir = dir.getDir(subdirs[i]); D.deb("Putting '"+subdirs[i]+"' under '"+subdir.getPath()+"' to cache."); if (subdir != null) { registerInMemoryCacheRecursive(subdir.getPath(), subdir); } } dirsByName.put(path,dir); } //------------------------------------------- private void unregisterFromMemoryCache(String path){ VcsDir dir=(VcsDir)dirsByName.get(path); if( dir==null ){ return ; } D.deb("unregisterFromMemoryCache('"+path+"',"+dir+")"); // NOI18N dirsByName.remove(path); } private void unregisterFromMemoryCacheRecursive(VcsDir dir){ String[] subdirs = dir.getSubdirs(); for(int i = 0; i < subdirs.length; i++) { VcsDir subdir = dir.getDir(subdirs[i]); if (subdir != null) { unregisterFromMemoryCacheRecursive(subdir); dirsByName.remove(subdir.getPath()); } } } //------------------------------------------- private String[] lineToStringArray(String line){ Vector vec=new Vector(10); int pos=0; int i=-1; String item=null; while( (i=line.indexOf("|",pos)) >= 0 ){ // NOI18N item=line.substring(pos,i); vec.addElement(item); pos=i+1; } String []sa=new String[vec.size()]; for(int j=0;j<vec.size();j++){ sa[j]=(String) vec.elementAt(j); } return sa; } //------------------------------------------- private void deleteDirFromDiskCache(String path){ //D.deb("deleteDirFromDiskCache('"+path+"')"); // NOI18N String dirName=cacheDir+ (path.equals("")?"":(File.separator+path)); // NOI18N File cacheFile=new File(dirName+File.separator+"list.txt"); // NOI18N if( cacheFile.exists() ){ //D.deb("deleting cacheFile="+cacheFile); // NOI18N if( cacheFile.delete()==false ){ E.err("Failed to delete "+cacheFile); // NOI18N } } } /** * Read contents of directory from disk cache and register directory into memory cache. * @return VcsDir object or null when the directory is not in cache */ //------------------------------------------- private VcsDir readDirFromDiskCache(String path){ D.deb("readDirFromDiskCache('"+path+"')"); // NOI18N String dirName=cacheDir+ (path.equals("")?"":(File.separator+path)); // NOI18N File cacheFile=new File(dirName+File.separator+"list.txt"); // NOI18N D.deb("cacheFile = "+cacheFile+", does"+(cacheFile.exists() ? "" : " not")+" exist"); if( cacheFile.exists() && cacheFile.canRead() ){ String name = MiscStuff.getFileNamePart(path); VcsDir dir=new VcsDir(name); dir.path = path; dir.setLoaded(true); try{ BufferedReader in= new BufferedReader (new InputStreamReader (new BufferedInputStream (new FileInputStream(cacheFile)))); String line=null; while( (line=in.readLine())!=null ){ String []sa=lineToStringArray(line); //D.deb("sa="+MiscStuff.arrayToString(sa)); // NOI18N VcsFile file=fileSystem.getVcsFactory().getVcsAction (fileSystem).parseFromCache(sa); if(file instanceof VcsDir) { ((VcsDir) file).setPath(path+((path.length() > 0) ? "/" : "")+file.getName()); } D.deb("file="+file); // NOI18N if (file.getStatus().equals(localStatusStr)) file.setLocal(true); dir.add(file); } // D.deb("disk cache hit for '"+path+"'"); // NOI18N registerInMemoryCache(path,dir); // readLocalDir (dir, path); return dir; }catch (IOException e){ E.err(e,"readDirFromDiskCache() failed"); // NOI18N return null ; } } return null ; } /** * To be called when any change on directory occures that results in diferent appearence. */ private void heyDoRefreshDir(String path){ FileObject fo=fileSystem.findResource(path); if( fo!=null ){ //D.deb("fo.refresh("+path+")"); // NOI18N fo.refresh(); } } /** * To be called when any change on directory occures that results in diferent appearence. */ private void heyDoRefreshDirRecursive(VcsDir dir){ String[] subdirs = dir.getSubdirs(); for(int i = 0; i < subdirs.length; i++) { VcsDir subdir = dir.getDir(subdirs[i]); D.deb("Refreshing '"+subdirs[i]+"'"); if (subdir != null) { heyDoRefreshDirRecursive(subdir); } } FileObject fo=fileSystem.findResource(dir.getPath()); if( fo!=null ){ //D.deb("fo.refresh("+path+")"); // NOI18N fo.refresh(); } } /** * Read list of files/directories in the specified directory on local disk * and add it to existing contents of the directory. Only files that were not * read from VCS are added. Registry each directory added into memory cache. */ //------------------------------------------- private void refreshLocalFiles (VcsDir dir, String path){ if(!localFilesAdd) return; // remove local files (they will be refreshed) dir.removeLocalFilesAndSubdirs (); String[] contents = dir.getFilesAndSubdirs(); // debug File localDir = new File (fileSystem.getRootDirectory (), path); if(localDir.exists() && localDir.canRead ()) { String[] files = localDir.list (fileSystem.getLocalFileFilter()); if (files != null) { for(int i=0; i<files.length; i++) { if(!dir.hasFile (files [i]) && !dir.hasSubdir (files [i])) { D.deb("Adding local file "+files[i]); // NOI18N VcsFile f; if ((new File(localDir, files[i])).isDirectory()) { f = new VcsDir(); String newPath = path.length ()==0 ? files[i] : path + "/" + files[i]; // NOI18N // System.out.println("dir path:" + newPath); // NOI18N ((VcsDir) f).path = newPath; if (!isDir(newPath)) { D.deb("Dir not in memory cache => REGISTERED"); registerInMemoryCache (newPath, (VcsDir) f); } } else f = new VcsFile(); f.name = files[i]; f.setLocal (true); f.status = localStatusStr; // System.out.println("localFile/Dir:"+f.name); // NOI18N dir.add (f); } } } } } private void refreshLocalFilesRecursively(VcsDir dir, String path) { refreshLocalFiles(dir, path); String[] subdirs = dir.getSubdirs(); for(int i = 0; i < subdirs.length; i++) { VcsDir subdir = dir.getDir(subdirs[i]); D.deb("Refreshing '"+subdirs[i]+"'"); if (subdir != null) { refreshLocalFilesRecursively(subdir, subdir.getPath()); } } } private synchronized void runDirReaderFromQueue() { if (pathsQueue.isEmpty()) return; String path=(String)pathsQueue.remove(0); D.deb(" ++++ runDirReaderFromQueue(): path = "+path); // NOI18N VcsDirReader reader= fileSystem.getVcsFactory ().getVcsDirReader (this, path, fileSystem); if (reader != null) { new Thread (reader, "VCS-DirReader").start(); // NOI18N numRefreshThreads++; lastCanceled = false; D.deb(" ++++ reader started, numRefreshThreads = "+numRefreshThreads); // NOI18N } else { fileSystem.debug(fileSystem.getBundleProperty("MSG_CommandCanceled")); // NOI18N lastCanceled = true; } } //------------------------------------------- private void readDir(String path, final boolean recursive){ D.deb("readDir('"+path+"')"); // NOI18N VcsDir dir=getDir(path); D.deb("dir = "+dir+", isLoaded() = "+((dir != null) ? new Boolean(dir.isLoaded()).toString() : "XXX")); D.deb("\t\t isLocal() = "+((dir != null) ? ""+dir.isLocal() : "XXX")); //boolean wasLocal = (dir != null && dir.isLocal()); // unknown or local files read from vcs disc cache if(dir==null || (!dir.isLocal() && !dir.isLoaded())) { dir=readDirFromDiskCache(path); //if (wasLocal) dir.setLocal(true); //dir.setLoaded(true); } // add local files to dir if(dir != null && (dir.isLoaded() || dir.isLocal())){ D.deb("dir = "+dir+", isLocal = "+dir.isLocal()); heyDoRefreshDir(path); return ; } dir=new VcsDir(); dir.path = path; dir.name = MiscStuff.getFileNamePart (dir.path); registerInMemoryCache(dir.path, dir); dir.setBeingLoaded(true); heyDoRefreshDir(dir.path); dir.setBeingLoaded(false); final String fPath = path; final VcsCache cache = this; if (!(lastCanceled && numRefreshThreads > 0)) { D.deb(" ++++ Running Read Dir Thread, path = "+fPath); // NOI18N if (!path.equals ("")) pathsQueue.add(path); // NOI18N //new Thread(new Runnable () { javax.swing.SwingUtilities.invokeLater(new Runnable () { public synchronized void run () { D.deb("Entering invokeLater"); // NOI18N if(recursive || (fPath.equals ("") && fileSystem.getAskIfDownloadRecursively() && // NOI18N NotifyDescriptor.Confirmation.YES_OPTION.equals ( TopManager.getDefault ().notify (new NotifyDescriptor.Confirmation ( fileSystem.getBundleProperty("DLG_DownloadRecursively"), NotifyDescriptor.Confirmation.YES_NO_OPTION))))) { // NOI18N VcsDirReader reader= fileSystem.getVcsFactory ().getVcsDirReaderRecursive (cache, fPath, fileSystem); if (reader != null) { new Thread (reader).start(); } else { fileSystem.getVcsFactory ().getVcsAction (fileSystem).doListSub (fPath); } } else { new Thread(new Runnable () { public void run () { if (fPath.equals ("")) pathsQueue.add(fPath); // I don't want to access pathQueue in the AWT thread // NOI18N } }).start(); //D.deb(" ++++ There is "+pathsQueue.size()+" items in the queue."); // NOI18N if (numRefreshThreads > 0) { D.deb(" ++++ Leaving for later, numRefreshThreads = "+numRefreshThreads); // NOI18N } else { new Thread(new Runnable () { public void run () { runDirReaderFromQueue(); // do not run this in AWT thread } }, "VCS-Run DirReader").start(); // NOI18N } /* D.deb(" ++++ getting the reader"); VcsDirReader reader= fileSystem.getVcsFactory ().getVcsDirReader (cache, fPath, fileSystem); if (reader != null) { new Thread (reader).start(); numRefreshThreads++; lastCanceled = false; D.deb(" ++++ reader started, numRefreshThreads = "+numRefreshThreads); } else { fileSystem.debug(fileSystem.getBundleProperty("MSG_CommandCanceled")); lastCanceled = true; } */ } fileSystem.setAskIfDownloadRecursively(true); D.deb("Finished invokeLater"); // NOI18N } });/*, "Read Dir Thread").start();*/ // NOI18N } else { D.deb(" ++++ Removing all paths queue"); // NOI18N pathsQueue.removeAllElements(); } } /** Called by VcsDirReader when asynchronous reading of directory is completed. * @param dir directory that was read by VcsDirReader * @param rawData vector of <CODE>String[]</CODE> that describes files and subdirectories, *it is stored in disk cache */ public synchronized void readDirFinished(VcsDir dir,Vector rawData, boolean success) { D.deb("readDirFinished(name="+dir.name+",path="+dir.path+",data="+rawData+")"); // NOI18N // Unregister subdirectories of the dir. This is necessary if subdirs have been // previously loaded from local fs and now they are added from vcs // since local sudirsdirs are registered in memory chache Enumeration en = dirsByName.keys (); String[] subs = dir.getSubdirs (); String pathPrefix = dir.path.length() == 0 ? "" : dir.path + "/"; // NOI18N /* for(int i=0; i<subs.length; i++) { // System.out.println (pathPrefix + subs[i]); VcsDir sub = getDir(pathPrefix + subs[i]); if (sub!=null && sub.isLocal ()) { unregisterFromMemoryCache (pathPrefix + subs[i]); } //D.deb("readDirFinished: "+sub.getName()+" status = "+sub.getStatus()); } */ writeDirToDiskCache(dir.path, rawData); registerInMemoryCache(dir.path, dir); for(int i=0; i<subs.length; i++) { VcsDir sub = getDir(pathPrefix + subs[i]); //D.deb("readDirFinished: "+sub.getName()+" status = "+sub.getStatus()); } heyDoRefreshDir(dir.path); fileSystem.statusChanged (dir.path, false); // perform non-recursive change of status if (numRefreshThreads > 0) numRefreshThreads--; D.deb(" ++++ numRefreshThreads = "+numRefreshThreads+" after readDirFinished."); // NOI18N D.deb(" ++++ Finished with "+success); // NOI18N if (!success) pathsQueue.removeAllElements(); D.deb(" ++++ number of items in the queue = "+pathsQueue.size()); // NOI18N if (!pathsQueue.isEmpty()) runDirReaderFromQueue(); } /** Called by VcsDirReader when asynchronous recursive reading of directory is completed. * @param dir directory that was read by VcsDirReader * @param rawData vector of <CODE>String[]</CODE> that describes files and subdirectories, *it is stored in disk cache */ public synchronized void readDirFinishedRecursive(VcsDir dir, VcsDirContainer rawData, boolean success) { D.deb("readDirFinished(name="+dir.name+",path="+dir.path+",data="+rawData+")"); // NOI18N // Unregister subdirectories of the dir. This is necessary if subdirs have been // previously loaded from local fs and now they are added from vcs // since local sudirsdirs are registered in memory chache Enumeration en = dirsByName.keys (); String[] subs = dir.getSubdirs (); String pathPrefix = (dir.path.length() == 0) ? "" : dir.path + "/"; // NOI18N unregisterFromMemoryCacheRecursive(dir); writeDirToDiskCacheRecursive(dir, rawData); registerInMemoryCacheRecursive(dir.path, dir); for(int i=0; i<subs.length; i++) { VcsDir sub = getDir(pathPrefix + subs[i]); //D.deb("readDirFinished: "+sub.getName()+" status = "+sub.getStatus()); } heyDoRefreshDirRecursive(dir); fileSystem.statusChanged (dir.path, true); // perform recursive change of status /* if (numRefreshThreads > 0) numRefreshThreads--; D.deb(" ++++ numRefreshThreads = "+numRefreshThreads+" after readDirFinished."); // NOI18N D.deb(" ++++ Finished with "+success); // NOI18N if (!success) pathsQueue.removeAllElements(); D.deb(" ++++ number of items in the queue = "+pathsQueue.size()); // NOI18N if (!pathsQueue.isEmpty()) runDirReaderFromQueue(); */ } /** Force refresh of directory. Delete the directory from cache * and read it. * @param path complete name of directory to refresh */ public void refreshDir(String path){ D.deb("refreshDir("+path+")"); // NOI18N // delete only files from vcs (not local) VcsDir dir = getDir(path); // true for all vcs dir (not local) // dir==null means it is vcs dir that is not in memory cache // !dir.local means it is vcs dir that is in memory cache if(dir==null || !dir.isLocal ()) { deleteDirFromDiskCache(path); if (dir != null) dir.setLoaded(false); } readDir(path, false); } /** Force recursive refresh of directory. Delete the directory from cache * and read it. * @param path complete name of directory to refresh */ public void refreshDirRecursive(String path){ D.deb("refreshDirRecursive("+path+")"); // NOI18N // delete only files from vcs (not local) VcsDir dir = getDir(path); // true for all vcs dir (not local) // dir==null means it is vcs dir that is not in memory cache // !dir.local means it is vcs dir that is in memory cache if(dir==null || !dir.isLocal ()) { deleteDirFromDiskCache(path); if (dir != null) dir.setLoaded(false); } readDir(path, true); } //------------------------------------------- /** This method should be called by file system to obtain complete *list of files and subdirectories of a directory. List of local files *and dirs is refreshed. * @param path path of directory * @return merged list of VCS and local files */ public String[] getFilesAndSubdirs(String path) { D.deb("getFilesAndSubdirs('"+path+"')"); // NOI18N VcsDir dir=(VcsDir)dirsByName.get(path); if(dir != null && (dir.isLoaded() || dir.isBeingLoaded() || dir.isLocal())) { D.deb("memory cache hit for '"+path+"'"); // NOI18N // refresh local subdirs and files refreshLocalFiles (dir, path); return dir.getFilesAndSubdirs(); } dir=readDirFromDiskCache(path); if (dir != null && (dir.isLoaded() || dir.isBeingLoaded() || dir.isLocal())) { D.deb("disk cache hit for '"+path+"'"); // NOI18N refreshLocalFiles (dir, path); return dir.getFilesAndSubdirs(); } D.deb("Did not found in memory nor in disk cache, calling readDir("+path+")"); readDir (path, false); return new String[0]; } /** This method should be called by file system to obtain complete * list of files and subdirectories of a directory. List only local files * and dirs. No Version Control command is run. * @param path path of directory * @return merged list of VCS and local files */ public String[] getLocalFilesAndSubdirs(String path) { D.deb("getLocalFilesAndSubdirs('"+path+"')"); // NOI18N VcsDir dir=(VcsDir)dirsByName.get(path); if (dir != null) { D.deb("memory cache hit for '"+path+"'"); // NOI18N // refresh local subdirs and files refreshLocalFiles (dir, path); return dir.getFilesAndSubdirs(); } dir=new VcsDir(); dir.path = path; dir.name = MiscStuff.getFileNamePart (dir.path); registerInMemoryCache(dir.path, dir); heyDoRefreshDir(dir.path); //refreshLocalFiles (dir, path); return dir.getFilesAndSubdirs(); } //------------------------------------------- /** Sorts directories and files so that dirs are first. * @param path path of directoru\ty * @param files original list of files and subdirs * @return sorted list */ public String[] dirsFirst(String path,String[] files) { //D.deb("dirsFirst("+path+", "+MiscStuff.arrayToString(files)); // NOI18N Vector dirsVec=new Vector(10); Vector filesVec=new Vector(20); String[] res=new String[files.length]; for(int i=0;i<files.length;i++){ String dir=path+files[i]; if( isDir(dir) || new File(dir).isDirectory() ){ dirsVec.addElement(files[i]); } else{ filesVec.addElement(files[i]); } } int dirsVecLen=dirsVec.size(); int filesVecLen=filesVec.size(); int j=0; for(int i=0;i<dirsVecLen;i++){ res[j++]= (String)dirsVec.elementAt(i); } for(int i=0;i<filesVecLen;i++){ res[j++]= (String)filesVec.elementAt(i); } return res; } //------------------------------------------- public String getStatus(Vector/*<VcsFile>*/ importantFiles){ D.deb("getStatus("+importantFiles+")"); // NOI18N String result=g("CTL_StatusNotInSync"); // NOI18N String status=""; // NOI18N int len=importantFiles.size(); VcsFile file=null; D.deb("len="+len); // NOI18N if( len<1 ){ return g("CTL_StatusUnknown"); // NOI18N } else if( len==1 ){ file=(VcsFile)importantFiles.elementAt(0); D.deb("one file status="+file.getStatus()); // NOI18N return file.getStatus(); } file=(VcsFile)importantFiles.elementAt(0); status=file.getStatus(); D.deb("status="+status); // NOI18N for(int i=1;i<len;i++){ file=(VcsFile)importantFiles.elementAt(i); //D.deb("file="+file); // NOI18N if( !file.getStatus().equals(status) ){ return result; } } return status; } //------------------------------------------- public void setFileStatus(String path, String status){ //D.deb("setFileStatus('"+path+"','"+status+"')"); // NOI18N VcsFile file=getFile(path); if( file==null ){ //if (path.length() > 0) E.err("file not found '"+path+"'"); // NOI18N // file was not found, status unchanged return ; } file.status=status; } //------------------------------------------- public String getFileStatus(String path){ //D.deb("getFileStatus('"+path+"')"); // NOI18N if( isFile(path) ){ VcsFile file=getFile(path); if( file==null ){ //E.err("cannot find file '"+path+"'"); // NOI18N return g("CTL_StatusNotInView"); // NOI18N } //D.deb("file.status='"+file.getStatus()+"'"); // NOI18N return file.getStatus(); } if( isDir(path) ){ VcsDir dir=getDir(path); if( dir==null ){ //E.err("cannot find dir '"+path+"'"); // NOI18N return g("CTL_StatusNotInView"); // NOI18N } //D.deb("dir.status='"+dir.getStatus()+"'"); // NOI18N return dir.getStatus(); } return g("CTL_StatusNotInView"); // NOI18N } public String getFileLocker(String path){ String locker = null; if (isFile(path)) { VcsFile file = getFile(path); if (file != null) locker = file.getLocker(); } return locker; } public String getLocker(Vector importantFiles) { String locker = null; int len = importantFiles.size(); for(int i = 0; i < len; i++) { VcsFile file = (VcsFile) importantFiles.elementAt(i); String fileLocker = file.getLocker(); if (locker == null) locker = fileLocker; else { if (fileLocker != null && fileLocker.length() > 0) { locker += " "+fileLocker; } } } return locker; } //------------------------------------------- public VcsDir getDir(String path){ String dirName=MiscStuff.getDirNamePart(path); String fileName=MiscStuff.getFileNamePart(path); VcsDir dir=(VcsDir)dirsByName.get(path); //D.deb("getDir("+path+") = "+dir); if( dir!=null ){ return dir; } dir=(VcsDir)dirsByName.get(dirName); //D.deb("getDir("+dirName+") = "+dir); if( dir!=null ){ return dir; } return null ; } //------------------------------------------- public VcsFile getFile(String path){ String dirName=MiscStuff.getDirNamePart(path); String fileName=MiscStuff.getFileNamePart(path); VcsDir dir=(VcsDir)dirsByName.get(dirName); if( dir==null ){ return null; } VcsFile file=dir.getFile(fileName); return file; } //------------------------------------------- public boolean isFile(String path){ //D.deb("isFile('"+path+"')"); // NOI18N if( isDir(path) ){ return false; } String dirName=MiscStuff.getDirNamePart(path); String fileName=MiscStuff.getFileNamePart(path); VcsDir dir=(VcsDir)dirsByName.get(dirName); if( dir==null ){ //D.deb("no"); // NOI18N return false; } if( dir.hasFile(fileName) ){ return true; } //D.deb("no"); // NOI18N return false; } //------------------------------------------- public boolean isDir(String path){ //D.deb("isDir('"+path+"')"); // NOI18N if( path.equals("") ){ // NOI18N return true ; } String dirName=MiscStuff.getDirNamePart(path); String fileName=MiscStuff.getFileNamePart(path); VcsDir dir=(VcsDir)dirsByName.get(path); if( dir!=null ){ return true ; } dir=(VcsDir)dirsByName.get(dirName); if( dir!=null ){ if( dir.hasSubdir(fileName) ){ return true ; } } //D.deb("no"); // NOI18N return false ; } //------------------------------------------- public void addFile(String path){ //D.deb("addFile('"+path+"')"); // NOI18N String dirName=MiscStuff.getDirNamePart(path); String fileName=MiscStuff.getFileNamePart(path); VcsDir dir=getDir(dirName); if (dir == null) { String dirNameName = MiscStuff.getFileNamePart(dirName); dir = new VcsDir(dirNameName); dir.setPath(dirName); dirsByName.put(dirName, dir); } VcsFile file=new VcsFile(fileName); dir.add(file); } //------------------------------------------- public void removeFile(String path){ //D.deb("removeFile('"+path+"')"); // NOI18N String dirName=MiscStuff.getDirNamePart(path); String fileName=MiscStuff.getFileNamePart(path); VcsDir dir = getDir(dirName); VcsFile file = getFile(path); if (dir != null) dir.remove(file); } //------------------------------------------- String g(String s) { //D.deb("getting "+s); return NbBundle.getBundle ("org.netbeans.modules.vcs.cmdline.Bundle").getString (s); } String g(String s, Object obj) { return MessageFormat.format (g(s), new Object[] { obj }); } String g(String s, Object obj1, Object obj2) { return MessageFormat.format (g(s), new Object[] { obj1, obj2 }); } String g(String s, Object obj1, Object obj2, Object obj3) { return MessageFormat.format (g(s), new Object[] { obj1, obj2, obj3 }); } } /* * $Log: * 24 Gandalf-post-FCS1.18.1.4 04/04/00 Martin Entlicher * 23 Gandalf-post-FCS1.18.1.3 04/04/00 Martin Entlicher Proper localized * output to the disk cache. * 22 Gandalf-post-FCS1.18.1.2 04/04/00 Martin Entlicher Small bug fix. * * 21 Gandalf-post-FCS1.18.1.1 03/30/00 Martin Entlicher Memory cache * changes. * 20 Gandalf-post-FCS1.18.1.0 03/23/00 Martin Entlicher Support for * recursive refresh by one command added, new folder denoting as local, add * new folders to cache only in case they are not there * (registerInMemoryCache()), added get of only local files * (getLocalFilesAndSubdirs()) * 19 Gandalf 1.18 03/09/00 Martin Entlicher Properly handle local * directories. * 18 Gandalf 1.17 02/11/00 Martin Entlicher * 17 Gandalf 1.16 02/10/00 Martin Entlicher Added statuses for * directories. Locking enabled. * 16 Gandalf 1.15 02/09/00 Martin Entlicher Fix when reading local * files from non-existent directory. * 15 Gandalf 1.14 02/09/00 Martin Entlicher * 14 Gandalf 1.13 01/19/00 Martin Entlicher * 13 Gandalf 1.12 01/17/00 Martin Entlicher Internationalization added * 12 Gandalf 1.11 01/15/00 Ian Formanek NOI18N * 11 Gandalf 1.10 01/07/00 Martin Entlicher Localization check * 10 Gandalf 1.9 12/28/99 Martin Entlicher Collect refresh requests * in the queue and deleting the queue when one command fails. * 9 Gandalf 1.8 12/21/99 Martin Entlicher * 8 Gandalf 1.7 12/16/99 Martin Entlicher * 7 Gandalf 1.6 12/01/99 Martin Entlicher Yuri Kamen's improvement * added * 6 Gandalf 1.5 11/09/99 Martin Entlicher * 5 Gandalf 1.4 11/09/99 Martin Entlicher * 4 Gandalf 1.3 10/26/99 Martin Entlicher * 3 Gandalf 1.2 10/25/99 Pavel Buzek copyright and log * 2 Gandalf 1.1 10/23/99 Ian Formanek NO SEMANTIC CHANGE - Sun * Microsystems Copyright in File Comment * 1 Gandalf 1.0 09/30/99 Pavel Buzek * $ */